package tdomhan.addict.parser;

import java.io.File;
import java.io.IOException;
import java.util.Locale;
import java.util.Vector;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import tdomhan.addict.dictionary.Dictionary;
import tdomhan.addict.dictionary.StardictFileCreator;

import com.ibm.icu.text.Collator;

/**
 * In order for this class to work you have to download the latest dump of the english wiktionary to the data folder
 * you can obtain it from: http://download.wikimedia.org/enwiktionary/latest/
 * don't forget unzipping it.
 *
 * this class mainly handles the XML stuff. The parsing of the wiktionary content is done in
 * @see TranslationParserStateMachine
 *
 * @author tobi
 *
 */
public class WiktionaryParser extends DefaultHandler{
	
	/**
	 * types of content.
	 * @author tobi
	 *
	 */
	enum Content {PAGE, TITLE, NONE};
	
	/**
	 * a buffer containing the actual wiktionary content.
	 * will be filled during parsing
	 */
	StringBuffer pageContent = new StringBuffer();
	StringBuffer title = new StringBuffer();
	
	Content currentContent = Content.NONE;
	
	/**
	 * will hold all the found translations after parsing.
	 */
	Vector<Translation> translations = new Vector<Translation>();
	/**
	 * handles the actual content parsing.
	 */
	TranslationParserStateMachine contentParser;
	
	/**
	 * 
	 * @param languageName the name of the language that shall be parsed in the wiktionary content. the first letter must be captial. example: Finnish
	 * @param languageNameShort short of languageName, will appear in the {{t|fi|...}} part of the wiktionary content. example: fi
	 */
	public WiktionaryParser(String languageName, String languageNameShort) {
		contentParser = new TranslationParserStateMachine(languageName, languageNameShort);
	}
	
	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		if(qName.equals("text")) {
			pageContent = new StringBuffer();
			currentContent = Content.PAGE;
		} else if(qName.equals("title")) {
			currentContent = Content.TITLE;
			title  = new StringBuffer();
		}
	}
	
	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		if(qName.equals("text")) {
			String[] lines = pageContent.toString().split("\\n|\\r");
			currentContent = Content.NONE;
			contentParser.reset();
			contentParser.setCurrentWord(title.toString());
			for(int i=0;i<lines.length;i++) {
				String line = lines[i];
				contentParser.parse(line);
			}
			translations.addAll(contentParser.getTranslations());
		} else if(qName.equals("title")) {
			currentContent = Content.NONE;
		}
	}
	
	@Override
	public void characters(char[] ch, int start, int length)
			throws SAXException {
		switch(currentContent) {
		case PAGE:
			pageContent.append(ch, start, length);
			break;
		case TITLE:
			title.append(ch, start, length);
			break;
		default:
		case NONE:
			break;
		}
	}
	
	public Vector<Translation> getTranslations() {
		return translations;
	}

	/**
	 * enwiktionary-20110110-pages-articles.xml leads to the following statistics:
	 *	total number of translations: 68349
	 * 	unique english words: 28361
	 *	unique finnish words: 39397
	 *  nice, hah?
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			Collator usCollator = Collator.getInstance(Locale.US);
			Collator fiCollator = Collator.getInstance(new Locale("fi"));
			Translation.setFirstLangCollator(usCollator);
			Translation.setSecondLangCollator(fiCollator);
			
			SAXParserFactory parserFac = SAXParserFactory.newInstance();
			SAXParser parser = parserFac.newSAXParser();
			WiktionaryParser wikParser = new WiktionaryParser("Finnish", "fi");

			//point the parser to the wiktionary xml dump you just downloaded.
			parser.parse("./data/enwiktionary-20110110-pages-articles.xml", wikParser);
			Vector<Translation> translations = wikParser.getTranslations();//en->fi
			
			System.out.println("total number of translations: " + translations.size());
			
			Dictionary dic = new Dictionary(usCollator, fiCollator);
			dic.constructFromTranslations(translations);
			
			System.out.println("unique english words: "+dic.getUniqueFirstLangWords().size());
			System.out.println("unique finnish words: "+dic.getUniqueSecondLangWords().size());
			
			//write out in the stardict file format
			new StardictFileCreator(dic).createStarDictFiles();
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
}
